package com.rykj.energy.common.utils;


import com.rykj.energy.common.dto.CameraDto;
import com.rykj.energy.common.enums.DeviceTypes;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class FFmpegUtils {

    /**
     * 海康RTSP格式
     * username(0): 用户名。例如admin。
     * password(1): 密码。例如12345。
     * ip(2): 为设备IP。例如 192.0.0.64。
     * port(3): 端口号默认为554，若为默认可不填写。
     * codec(4)：有h264、MPEG-4、mpeg4这几种。
     * channel(5): 通道号，起始为1。例如通道1，则为ch1。
     * subtype(6): 码流类型，主码流为main，辅码流为sub。
     */
    private static String HIK_RTSP = "rtsp://{0}:{1}@{2}:{3}/h264/ch{5}/{6}/av_stream";

    /**
     * 大华RTSP格式
     * username(0): 用户名。例如admin。
     * password(1): 密码。例如admin。
     * ip(2): 为设备IP。例如 10.7.8.122。
     * port(3): 端口号默认为554，若为默认可不填写。
     * channel(4): 通道号，起始为1。例如通道2，则为channel=2。
     * subtype(5): 码流类型，主码流为0（即subtype=0），辅码流为1（即subtype=1）。
     */
    private static String DHUA_RTSP = "rtsp://{0}:{1}@{2}:{3}/cam/realmonitor?channel={4}&subtype={5}";

    /**
     * 宇视RTSP格式
     * username(0): 用户名。例如admin。
     * password(1): 密码。例如admin。
     * ip(2): 为设备IP。例如 10.7.8.122。
     * port(3): 端口号默认为554，若为默认可不填写。
     * subtype(4): 码流类型，主码流为1，辅码流为2。
     * 新格式（待验证）:rtsp://username:password@<ip>:<port>/unicast/c<channel>/s<subtype>/live
     */
    private static String YUS_RTSP = "rtsp://{0}:{1}@{2}:{3}/video{4}";

    /**
     * 天地伟业RTSP格式（暂未找到正确格式，待验证）
     * ip(0)
     * port(1)
     */
    private static String TDWY_RTSP = "rtsp://{0}:{1}";

    /**
     *
     * @param ffmpegExePath   ffmpeg 服务程序 安装路径
     * @param rtspUrl  摄像头rtsp地址
     * @param savePicturePath  抓取图片保存的图片路径
     * @param picName 图片名称
     */
    public static void getCaptureByRtsp(String ffmpegExePath, String rtspUrl, String savePicturePath,String picName) throws Exception {

        FileUtils.mkdir(savePicturePath);//文件夹不存在，则创建
        List commend = new ArrayList();
        commend.add(ffmpegExePath);
        commend.add("-i");
        commend.add(rtspUrl);
//        commend.add("-s");
//        commend.add("4096*1800");
        commend.add("-b");
        commend.add("4M");
        commend.add("-y");
        commend.add("-f");
       // commend.add("image2");
        commend.add("mjpeg");
        commend.add("-vframes");
        commend.add("1");
       // commend.add("-an");
      //  commend.add("-loglevel");
       // commend.add("8");
        commend.add(savePicturePath + File.separator + picName);
        Process p = null;
        try {
          //  Process videoProcess = new ProcessBuilder(commend).start();
            log.info("ffmpeg命令===>{}",commend);
            ProcessBuilder builder = new ProcessBuilder(commend);
            builder.command(commend);
            p = builder.start();
            p.getOutputStream().close();
            doWaitFor(p);
            p.destroy();
//            dealStream(videoProcess);
//            videoProcess.waitFor();
        } catch (Exception e) {
            log.error("====ffmpeg连接摄像头截图异常:" + rtspUrl,e);
            p.destroy();
            throw new Exception(e);
        }
    }


    public static int doWaitFor(Process p) throws Exception {
        InputStream in = null;
        InputStream err = null;
        int exitValue = -1;

        try {
            in = p.getInputStream();
            err = p.getErrorStream();
            boolean finished = false;
            int i = 0;
            while(!finished) {
                try {
                    /*Character c;
                    while(in.available() > 0) {
                        c = new Character((char)in.read());
                        System.out.println(c);
                    }

                    while(err.available() > 0) {
                        c = new Character((char)err.read());
                        System.out.println(c);
                    }*/

                    exitValue = p.exitValue();
                    finished = true;
                } catch (IllegalThreadStateException var19) {
                    Thread.currentThread();
                    Thread.sleep(500L);
                    if(i>=20){ //重试次数,10秒
                        finished = true;
                        log.error("图片抓取超时");
                        throw new Exception("图片抓取超时");
                    }
                    i++;
                }
            }
        } catch (Exception var20) {
            throw new Exception(var20);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException var18) {
            }

            if (err != null) {
                try {
                    err.close();
                } catch (IOException var17) {
                }
            }

        }

        return exitValue;
    }

    /**
     * 返回摄像头对应的RTSP地址
     * @param cameraDto
     * @return
     */
    public static String getRtsp(CameraDto cameraDto){

        String rtsp = cameraDto.getRtspUrl();
        if(cameraDto.getDevType().equals(DeviceTypes.camera.getCode())){

            switch (cameraDto.getCamBrands()){ //设备品牌

                case "hk":
                    // subtype(6): 码流类型，主码流为main，辅码流为sub
                    String subtype = "main";
                    if(cameraDto.getStreamType()!=null && cameraDto.getStreamType()==1){//子码流
                        subtype = "sub";
                    }
                    Integer channel = 1;
                    if(cameraDto.getChannelIndex()!=null){
                        channel = cameraDto.getChannelIndex();
                    }
                    rtsp = MessageFormat.format(HIK_RTSP,cameraDto.getDevUser(),cameraDto.getDevPwd(),cameraDto.getDevAddress(),cameraDto.getDevPort().toString(),"",channel,subtype);
                    break;

                case "dh":
                    // subtype(6): 码流类型，主码流为main，辅码流为sub
                    rtsp = MessageFormat.format(DHUA_RTSP,cameraDto.getDevUser(),cameraDto.getDevPwd(),cameraDto.getDevAddress(),cameraDto.getDevPort(),cameraDto.getChannelIndex(),cameraDto.getStreamType()!=null?cameraDto.getStreamType():0);
                    break;

                case "ys":
                    // subtype(6): 码流类型，主码流为main，辅码流为sub
                    rtsp = MessageFormat.format(YUS_RTSP,cameraDto.getDevUser(),cameraDto.getDevPwd(),cameraDto.getDevAddress(),cameraDto.getDevPort(),cameraDto.getStreamType());
                    break;

                case "tiandy":
                    // subtype(6): 码流类型，主码流为main，辅码流为sub
                    rtsp = MessageFormat.format(TDWY_RTSP,cameraDto.getDevAddress(),cameraDto.getDevPort());
                    break;
            }
        }
        log.info("============摄像头RTSP：" + rtsp);
        return rtsp;
    }

    /**
     * 开启线程处理Ffmpeg处理流
     *
     * @param process
     */
    private static void dealStream(Process process) {
        if (process == null) {
            return;
        }
        // 处理InputStream的线程
        new Thread() {
            @Override
            public void run() {
                BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
                String line = null;
                try {
                    while ((line = in.readLine()) != null) {
                        log.warn("output: " + line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        // 处理ErrorStream的线程
        new Thread() {
            @Override
            public void run() {
                BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                String line = null;
                try {
                    while ((line = err.readLine()) != null) {
                        log.warn("output: " + line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        err.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }


    public static void main(String[] args) throws Exception {
        String ffmpegPath = "D:\\ffmpeg-n4.3.1\\bin\\ffmpeg.exe";
        String rtspUrl = "rtsp://admin:12qwaszx@192.168.0.195:554/cam/realmonitor?channel=1&subtype=0";
        String photoPath = "D:\\tmp\\ddr400\\camera\\dd";
        getCaptureByRtsp(ffmpegPath,rtspUrl,photoPath,"ddr.jpg");
    }
}